package com.android.monee.view.model;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.android.monee.binding.Field;
import com.android.monee.binding.observable.ObservableImpl;
import com.android.monee.data.access.BudgetDao;
import com.android.monee.data.access.DaoFactory;
import com.android.monee.data.model.Budget;
import com.android.monee.domain.BudgetService;

public class NewBudget extends ObservableImpl<NewBudget>{

	private String name;
	private String totalAmount;
	private String provAmount;
	private String begin;
	private String term;
	private List<String> validationErrors;
	private SimpleDateFormat sdf;
	
	public NewBudget(){
		super();
		this.sdf = new SimpleDateFormat("dd/MM/yy");
		this.validationErrors = new ArrayList<String>();
			
		initDefaultValues();	
	}
	
	public void initDefaultValues(){
		this.setName("");
		this.setTotalAmount("");
		this.setProvAmount("0");
		
		Date today = new Date();
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.YEAR, 1);
		Date inOneYear = cal.getTime();
		
		this.setBegin(sdf.format(today));
		this.setTerm(sdf.format(inOneYear));
		
		this.validationErrors.clear();
		notify(ValidationErrors.class);
	}
	
	/**
	 * Retourne un budget initialisé avec les valeurs saisies ou null.
	 * @return Le nouveau budget instancié ou null en cas de données invalides.
	 */
	public Budget ifValidCreateBudget (){
		this.validationErrors.clear();
		
		if(this.name == null || this.name.equals(""))
			this.validationErrors.add("Veuillez saisir un nom pour le budget.");
		
		float totalAmountFloat = 0;
		try{
			totalAmountFloat = Float.parseFloat(this.totalAmount);
		}catch (NumberFormatException e){
			this.validationErrors.add("Le nombre entré pour le montant total n'est pas valide.");
		}
		if(totalAmountFloat <= 0)
			this.validationErrors.add("Le montant total doit être positif.");
		
		if(this.provAmount == null || this.provAmount.equals(""))
			this.provAmount = "0";
		
		float provAmountFloat = 0;
		try{
			provAmountFloat = Float.parseFloat(this.provAmount);
		}catch (NumberFormatException e){
			this.validationErrors.add("Le nombre entré pour le montant provisionné n'est pas valide.");
		}
		
		if(this.begin == null || this.begin.equals(""))
			this.validationErrors.add("La date de début n'est pas valide.");
		
		if(this.term == null || this.term.equals(""))
			this.validationErrors.add("La date d'échéance n'est pas valide.");
		
		Date beginDate = null;
		Date termDate = null;
		if(this.begin != null && this.term != null){
			try {
				beginDate = sdf.parse(begin);
				termDate = sdf.parse(term);
				
				Calendar cal = Calendar.getInstance();
				if(beginDate.compareTo(termDate) >= 0)
					this.validationErrors.add("La date d'échéance doit être postérieure à la date de début.");
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		
		notify(ValidationErrors.class);
		
		if(this.validationErrors.isEmpty()){
			return new BudgetService(this.name,
					totalAmountFloat, 
					provAmountFloat,
					beginDate,
					termDate);
		}else
			return null; 
	}
	
	public boolean createInsertNewBudget(){
		Budget budget = ifValidCreateBudget();
		if(budget != null){
			BudgetService.insert(budget);
			initDefaultValues();
		}
		return budget != null;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
		super.notify(Name.class);
	}

	public String getTotalAmount() {
		return totalAmount;
	}

	public void setTotalAmount(String totalAmount) {
		this.totalAmount = totalAmount;
		super.notify(TotalAmount.class);
	}

	public String getProvAmount() {
		return provAmount;
	}

	public void setProvAmount(String provAmount) {
		this.provAmount = provAmount;
		super.notify(ProvAmount.class);
	}

	public String getBegin() {
		return begin;
	}

	public void setBegin(String begin) {
		this.begin = begin;
		super.notify(Begin.class);
	}

	public String getTerm() {
		return term;
	}

	public void setTerm(String term) {
		this.term = term;
		super.notify(Term.class);
	}

	public List<String> getValidationErrors() {
		return validationErrors;
	}

	public SimpleDateFormat getSdf() {
		return sdf;
	}
	
	public class Name implements Field<NewBudget, String>{
		@Override
		public String get(NewBudget obj) {
			return obj.getName();
		}
		@Override
		public void set(NewBudget obj, String val) {
			obj.setName(val);
		}
		
	}
	public class TotalAmount implements Field<NewBudget, String>{
		@Override
		public String get(NewBudget obj) {
			return obj.getTotalAmount();
		}
		@Override
		public void set(NewBudget obj, String val) {
			obj.setTotalAmount(val);
		}
		
	}
	public class ProvAmount implements Field<NewBudget, String>{
		@Override
		public String get(NewBudget obj) {
			return obj.getProvAmount();
		}
		@Override
		public void set(NewBudget obj, String val) {
			obj.setProvAmount(val);
		}
		
	}
	public class Begin implements Field<NewBudget, String>{
		@Override
		public String get(NewBudget obj) {
			return obj.getBegin();
		}
		@Override
		public void set(NewBudget obj, String val) {
			obj.setBegin(val);
		}
		
	}
	public class Term implements Field<NewBudget, String>{
		@Override
		public String get(NewBudget obj) {
			return obj.getTerm();
		}
		@Override
		public void set(NewBudget obj, String val) {
			obj.setTerm(val);
		}
		
	}
	public class ValidationErrors implements Field<NewBudget, List<String>>{
		@Override
		public List<String> get(NewBudget obj) {
			return obj.getValidationErrors();
		}
		@Override
		public void set(NewBudget obj, List<String> val) {
			//TODO : gerer one way et two way binding
			System.err.println("La propriété ValidationErrors du NewBudget2 n'est pas accessible en écriture");
		}
		
	}

}
